/*******************************************************************************
 *BSD 3-Clause License
 *
 *Copyright (c) 2016-2022, Mech-Mind Robotics
 *All rights reserved.
 *
 *Redistribution and use in source and binary forms, with or without
 *modification, are permitted provided that the following conditions are met:
 *
 *1. Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *2. Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 *3. Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

#pragma once
#include <string>

namespace mmind {

namespace api {

/**
 * @brief This enumeration defines the types of errors.
 */
struct ErrorStatus
{
    enum ErrorCode {
        MMIND_STATUS_SUCCESS = 0,         ///< Success status.
        MMIND_STATUS_INVALID_DEVICE = -1, ///< Error invalid device.
        MMIND_STATUS_DEVICE_OFFLINE =
            -2, ///< Error offline device. Please check the status of the device.
        MMIND_STATUS_FIRMWARE_NOT_SUPPORTED =
            -3, ///< Error not supported camera firmware. Please use MechEye Viewer to upgrade.
        MMIND_STATUS_PARAMETER_SET_ERROR = -4, ///< Error setting parameter to device.
        MMIND_STATUS_PARAMETER_GET_ERROR = -5, ///< Error reading parameter from device.
        MMIND_STATUS_CAPTURE_NO_FRAME = -6,    ///< Error no frame is captured.
    };
    ErrorStatus() = default;
    ErrorStatus(ErrorCode code, const std::string& message)
        : errorCode(code), errorDescription(message)
    {
    }

    bool isOK() const { return errorCode == MMIND_STATUS_SUCCESS; }

    /**
     * Error code.
     */
    ErrorCode errorCode{MMIND_STATUS_SUCCESS};

    /**
     * Detailed error message.
     */
    std::string errorDescription;
};

/**
 * @brief This struct defines device information.
 */
struct MechEyeDeviceInfo
{
    std::string model; ///< Device model name, such as Mech-Eye Nano.
    std::string id;    ///< Device ID.
    std::string
        hardwareVersion; ///< The version of the hardware which is pre-determined from the factory.
    std::string firmwareVersion; ///< The version of the firmware which can be upgraded.
    std::string ipAddress;       ///< IP address of the device.
    uint16_t port;               ///< Device port.
};

/**
 * @brief This struct defines camera intrinsic parameters.
 */
struct CameraIntri
{
    double distortion[5] = {}; ///< Vector of distortion coefficients, which arrange in [k1, k2, p1,
                               ///< p2, k3].
    double cameraMatrix[4] = {}; ///< Camera matrix, which arrange in [fx, fy, cx, cy].
};

/**
 * @brief This struct defines rigid body transformations, including rotation matrix and
 * translation vector.
 */
struct Pose
{
    double rotation[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; ///< 3*3 rotation matrix.
    double translation[3] = {0, 0, 0}; ///< 3*1 translation vector in [x(mm), y(mm), z(mm)].
};

/**
 * @brief This struct defines device intrinsic parameters, including texture camera and depth
 * camera.
 */
struct DeviceIntri
{
    CameraIntri
        textureCameraIntri; /// The intrinsic parameters of the camera for capturing color map.
    CameraIntri
        depthCameraIntri; /// The intrinsic parameters of the camera for capturing depth map.

    Pose depthToTexture; /// The rigid body transformation from depth camera coordinate
                         /// system to texture camera coordinate system. There is no transform
                         /// when texture camera and depth camera are the same.
};

/**
 * @brief This struct defines camera map resolution.
 */
struct DeviceResolution
{
    unsigned colorMapWidth;  ///< The width of the color map.
    unsigned colorMapHeight; ///< The height of the color map.
    unsigned depthMapWidth;  ///< The width of the depth map.
    unsigned depthMapHeight; ///< The height of the depth map.
};

/**
 * @brief This struct defines camera region of interest.
 */
struct ROI
{
    ROI() = default;
    ROI(int x, int y, int width, int height) : x(x), y(y), width(width), height(height) {}
    unsigned x;      ///< The column coordinates of the upper left point of the region of interest.
    unsigned y;      ///< The row coordinates of the upper left point of the region of interest.
    unsigned width;  ///< The width of the region of interest.
    unsigned height; ///< The height of the region of interest.
};

/**
 * @brief This struct defines the depth range.
 */
struct DepthRange
{
    DepthRange() = default;
    DepthRange(int lower, int upper) : lower(lower), upper(upper) {}
    int lower; ///< The lower limit of the roi on the z value of the depth map in the
               ///< camera coordinate system.
    int upper; ///< The upper limit of the roi on the z value of the depth map in the
               ///< camera coordinate system
};
} // namespace api
} // namespace mmind
